package com.zdd.ehe.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.zdd.ehe.dto.UserDto;
import com.zdd.ehe.entity.User;
import com.zdd.ehe.entity.UserRole;
import com.zdd.ehe.result.Result;
import com.zdd.ehe.service.IRoleService;
import com.zdd.ehe.service.IUserRoleService;
import com.zdd.ehe.service.IUserService;
import com.zdd.ehe.util.JwtUtil;
import com.zdd.ehe.util.PBKDF2Util;
import com.zdd.ehe.vo.UserVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @title:AccountController
 * @author:ZhuZhui
 * @description:登录模块
 * @createDate: 2023/3/14  14:48
 */
@Api(tags = "登录模块")
@RestController
@RequestMapping("/account")
public class AccountController {

    @Resource
    private JwtUtil jwtUtil;
    @Resource
    private IUserService userService;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private IRoleService roleService;
    @Resource
    private IUserRoleService userRoleService;
    // 日志对象
    private static final transient Logger log = LoggerFactory.getLogger(UserController.class);

    //登录
    @ApiOperation("登录接口")
    @PostMapping("/login")
    public Result login(@RequestBody UserDto userDto, HttpServletResponse response){
        User user = userService.getOne(new QueryWrapper<User>().eq("account", userDto.getUsername()));
        if(user == null){
            return Result.error(4001,"用户不存在");
        }
        if(user.getDel().equals("0")){
            return Result.error(4005,"该账号已被删除");
        }
        //获取主体对象
        Subject subject = SecurityUtils.getSubject();
        String password = "";
        try {
            // 加密比较
            password = PBKDF2Util.getEncryptedPassword(userDto.getPassword(),user.getSalt());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return Result.error(4004,"出现异常,请稍后再试");
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
            return Result.error(4004,"出现异常,请稍后再试");
        }

        // 登录
        AuthenticationToken token = new UsernamePasswordToken(userDto.getUsername(),password);
        try {
            subject.login(token);
        }catch (UnknownAccountException uae){ // 用户名不对抛出异常
            log.info("用户名错误");
            return Result.error(4001,"用户不存在");
        }catch(IncorrectCredentialsException ice){ // 密码不对抛出异常
            log.info("密码错误");
            return Result.error(4002,"密码错误,请重新输入");
        }catch(LockedAccountException lae){ // 用户锁定抛出异常
            log.info("用户账号锁定");
            return Result.error(4003,"抱歉,您的账号已被锁定");
        }catch(AuthenticationException ae){
            log.info("其它异常");
            return Result.error(4004,"出现异常,请稍后再试");
        }

        // po vo 转换
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user,userVo);

        // 获取用户角色列表
        List<String> roleList = userService.getRoles(user.getId());
        //System.out.println("用户角色列表: " + roleList);
        // 根据角色列表获取权限集合
        Set<String> permissionSet = new HashSet<>();
        for(int i=0;i<roleList.size();i++){
            List<String> permissions = roleService.getPermissions(roleList.get(i));
            for(int j=0;j<permissions.size();j++){
                permissionSet.add(permissions.get(j));
            }
        }

        List<String> permissionList = new ArrayList<>(permissionSet);
        userVo.setRoles(roleList);
        userVo.setPermissions(permissionList);

        Gson gson = new Gson();
        // 向redis中存入用户权限、用户角色
        redisTemplate.opsForValue().set(userVo.getId().toString() + "_p", gson.toJson(permissionSet));
        redisTemplate.opsForValue().set(userVo.getId().toString() + "_r", gson.toJson(roleList));

        String jwt = jwtUtil.createToken(userVo);
        response.setHeader("token",jwt);
        response.setHeader("Access-Control-Expose-Headers","token");

       log.info(new Date() + " - " + userVo.getUserName() + " 欢迎登录 ");

        return Result.success("登录成功!",userVo);
    }

    //注册
    @ApiOperation("注册接口")
    @PostMapping("/register")
    public Result register(@RequestBody User user){
        String avatar = "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif?imageView2/1/w/80/h/80";

        if(user.getAccount() == null || user.getUserName() == null || user.getPassword() == null || avatar == null){
            return Result.error(4001, "参数缺失");
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account", user.getAccount());
        User userx = userService.getOne(queryWrapper);
        if(userx != null){
            return Result.error(4002, "账号已被注册");
        }

        if(!user.getDel().equals("0")){
            user.setDel("1");
        }
        // 数据处理
        user.setRegisttm(LocalDateTime.now());
        user.setUserUuid(UUID.randomUUID().toString());
        String salt = "";
        // 密码加密
        try {
            salt = PBKDF2Util.generateSalt();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return Result.error(4003,"出现异常,请稍后再试");
        }

        String password = "";
        try {
            password = PBKDF2Util.getEncryptedPassword(user.getPassword(),salt);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return Result.error(4003,"出现异常,请稍后再试");
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
            return Result.error(4003,"出现异常,请稍后再试");
        }
        user.setSalt(salt);
        user.setPassword(password);
        user.setAvatar(avatar);

        // 传入数据库
        int result = userService.insert(user);
        if(result != 1){
            return Result.error(4004,"数据保存失败");
        }

        //获取数据库中的数据
        queryWrapper.eq("account", user.getAccount());
        User user1 = userService.getOne(queryWrapper);



        userRoleService.insert(new UserRole(user1.getId(),2,LocalDateTime.now(),"1"));

        // po vo 转换
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user1,userVo);

        return Result.success("注册成功",userVo);

    }

    //退出
    @ApiOperation("退出接口")
    @GetMapping("/logout")
    @RequiresAuthentication
    public Result logout() {
        SecurityUtils.getSubject().logout();
        return Result.success("退出成功!");
    }


}
